home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / term / extras / source / term-source.lha / termDial.c < prev    next >
C/C++ Source or Header  |  1995-06-19  |  41KB  |  1,868 lines

  1. /*
  2. **    termDial.c
  3. **
  4. **    The dialing routine as called by the phonebook
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Panel gadget IDs. */
  15.  
  16. enum    {    GAD_CALLING=1,GAD_TIME,GAD_NOTE,
  17.             GAD_SKIP,GAD_REMOVE,GAD_ONLINE,GAD_ABORT
  18.         };
  19.  
  20. STATIC VOID __stdargs
  21. PrintBox(struct LayoutHandle *Handle,LONG Box,LONG Line,STRPTR String,...)
  22. {
  23.     UBYTE     LocalBuffer[256];
  24.     va_list     VarArgs;
  25.  
  26.     va_start(VarArgs,String);
  27.     VSPrintf(LocalBuffer,String,VarArgs);
  28.     va_end(VarArgs);
  29.  
  30.     LT_SetAttributes(Handle,Box,
  31.         LABX_Index,    Line,
  32.         LABX_Text,    LocalBuffer,
  33.     TAG_DONE);
  34. }
  35.  
  36.     /* BuildName(STRPTR Name):
  37.      *
  38.      *    Build a file name from a BBS name and the current date.
  39.      */
  40.  
  41. STATIC VOID __regargs
  42. BuildName(STRPTR Name,STRPTR Date)
  43. {
  44.     if(Date[0])
  45.     {
  46.         WORD    NameLen = strlen(Name),
  47.                 DateLen = strlen(Date),
  48.                 Delta;
  49.  
  50.         if((Delta = NameLen + 1 + DateLen - 32) > 0)
  51.             Name[NameLen - Delta] = 0;
  52.  
  53.         strcat(Name,"_");
  54.         strcat(Name,Date);
  55.     }
  56. }
  57.  
  58.     /* OpenAutoCaptureFile(STRPTR SomeName):
  59.      *
  60.      *    Open a capture file.
  61.      */
  62.  
  63. STATIC VOID __regargs
  64. OpenAutoCaptureFile(STRPTR SomeName)
  65. {
  66.     UBYTE            SharedBuffer[MAX_FILENAME_LENGTH],
  67.                     Name[50],
  68.                     Date[20],
  69.                     Time[20];
  70.     struct DateTime    DateTime;
  71.  
  72.         /* Get the current time and date. */
  73.  
  74.     DateStamp(&DateTime . dat_Stamp);
  75.  
  76.         /* Prepare for date conversion. */
  77.  
  78.     DateTime . dat_Format    = FORMAT_DOS;
  79.     DateTime . dat_Flags    = 0;
  80.     DateTime . dat_StrDay    = NULL;
  81.     DateTime . dat_StrDate    = Date;
  82.     DateTime . dat_StrTime    = Time;
  83.  
  84.         /* Convert the date. */
  85.  
  86.     if(DateToStr(&DateTime))
  87.     {
  88.             /* Remember the BBS name. */
  89.  
  90.         strcpy(Name,SomeName);
  91.  
  92.             /* Append the creation date if necessary. */
  93.  
  94.         if(Config -> CaptureConfig -> AutoCaptureDate == AUTOCAPTURE_DATE_NAME)
  95.             BuildName(Name,Date);
  96.  
  97.             /* Make it a reasonable name. */
  98.  
  99.         FixName(Name);
  100.  
  101.             /* Get the capture file path. */
  102.  
  103.         strcpy(SharedBuffer,Config -> CaptureConfig -> CapturePath);
  104.  
  105.             /* Try to build a valid file and path name. */
  106.  
  107.         if(AddPart(SharedBuffer,Name,MAX_FILENAME_LENGTH))
  108.         {
  109.                 /* Is the capture file still open? */
  110.  
  111.             if(FileCapture)
  112.             {
  113.                     /* Close the file. */
  114.  
  115.                 BufferClose(FileCapture);
  116.  
  117.                 FileCapture = NULL;
  118.  
  119.                     /* Any data written? */
  120.  
  121.                 if(!GetFileSize(CaptureName))
  122.                     DeleteFile(CaptureName);
  123.                 else
  124.                 {
  125.                     AddProtection(CaptureName,FIBF_EXECUTE);
  126.  
  127.                     if(Config -> MiscConfig -> CreateIcons)
  128.                         AddIcon(CaptureName,FILETYPE_TEXT,TRUE);
  129.                 }
  130.             }
  131.  
  132.                 /* Try to append the new data. */
  133.  
  134.             if(FileCapture = BufferOpen(SharedBuffer,"a"))
  135.             {
  136.                     /* Set the menu checkmark. */
  137.  
  138.                 CheckItem(MEN_CAPTURE_TO_FILE,TRUE);
  139.  
  140.                     /* Remember the current capture file name. */
  141.  
  142.                 strcpy(CaptureName,SharedBuffer);
  143.  
  144.                     /* Add the creation date if necessary. */
  145.  
  146.                 if(Config -> CaptureConfig -> AutoCaptureDate == AUTOCAPTURE_DATE_INCLUDE)
  147.                 {
  148.                     UBYTE DateTimeBuffer[256];
  149.  
  150.                     if(FormatStamp(&DateTime . dat_Stamp,NULL,NULL,DateTimeBuffer,FALSE))
  151.                         BPrintf(FileCapture,LocaleString(MSG_DIALPANEL_FILE_CREATED_TXT),DateTimeBuffer);
  152.                 }
  153.             }
  154.             else
  155.                 CheckItem(MEN_CAPTURE_TO_FILE,FALSE);
  156.  
  157.             ConOutputUpdate();
  158.         }
  159.     }
  160. }
  161.  
  162.     /* Connect(struct PhoneNode *DialNode,STRPTR NumberBuffer):
  163.      *
  164.      *    Perform connect action(s).
  165.      */
  166.  
  167. STATIC VOID __regargs
  168. Connect(struct PhoneNode *DialNode,STRPTR NumberBuffer)
  169. {
  170.     if(DialNode -> Entry)
  171.     {
  172.         UpdateConfig(DialNode -> Entry -> Config,Config);
  173.  
  174.         ConfigChanged = FALSE;
  175.  
  176.         MakeCall(DialNode -> Entry -> Header -> Name,NumberBuffer);
  177.  
  178.         ObtainSemaphore(&PatternSemaphore);
  179.  
  180.         ChosenPattern = FindTimeDate(PatternList,NumberBuffer);
  181.  
  182.         SelectTime(DialNode -> Entry,ChosenPattern,NULL);
  183.  
  184.         ChosenEntry    = DialNode -> Entry;
  185.         WhichUnit    = DT_FIRST_UNIT;
  186.         CurrentPay    = 0;
  187.         SendStartup    = TRUE;
  188.  
  189.         ReleaseSemaphore(&PatternSemaphore);
  190.  
  191.         strcpy(Password,DialNode -> Entry -> Header -> Password);
  192.         strcpy(UserName,DialNode -> Entry -> Header -> UserName);
  193.  
  194.         strcpy(CurrentBBSName,DialNode -> Entry -> Header -> Name);
  195.         strcpy(CurrentBBSComment,DialNode -> Entry -> Header -> Comment);
  196.  
  197.         strcpy(CurrentBBSNumber,NumberBuffer);
  198.  
  199.         if(DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
  200.         {
  201.             OnlinePlus = DialNode -> Entry -> Config -> ModemConfig -> TimeToConnect;
  202.  
  203.             if(DialNode -> Entry -> Config -> ModemConfig -> ConnectLimit > 0 && DialNode -> Entry -> Config -> ModemConfig -> ConnectLimitMacro[0])
  204.             {
  205.                 LimitCount = DialNode -> Entry -> Config -> ModemConfig -> ConnectLimit;
  206.  
  207.                 strcpy(LimitMacro,DialNode -> Entry -> Config -> ModemConfig -> ConnectLimitMacro);
  208.             }
  209.             else
  210.                 LimitCount = -1;
  211.         }
  212.         else
  213.         {
  214.             OnlinePlus = Config -> ModemConfig -> TimeToConnect;
  215.  
  216.             if(Config -> ModemConfig -> ConnectLimit > 0 && Config -> ModemConfig -> ConnectLimitMacro[0])
  217.             {
  218.                 LimitCount = Config -> ModemConfig -> ConnectLimit;
  219.  
  220.                 strcpy(LimitMacro,Config -> ModemConfig -> ConnectLimitMacro);
  221.             }
  222.             else
  223.                 LimitCount = -1;
  224.         }
  225.  
  226.         LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_1_TXT),DialNode -> Entry -> Header -> Name,NumberBuffer);
  227.     }
  228.     else
  229.     {
  230.         OnlinePlus = Config -> ModemConfig -> TimeToConnect;
  231.  
  232.         MakeCall("???",NumberBuffer);
  233.  
  234.         ObtainSemaphore(&PatternSemaphore);
  235.  
  236.         ChosenPattern = FindTimeDate(PatternList,NumberBuffer);
  237.  
  238.         SelectTime(NULL,ChosenPattern,NULL);
  239.  
  240.         ChosenEntry    = NULL;
  241.  
  242.         ReleaseSemaphore(&PatternSemaphore);
  243.  
  244.         CurrentPay    = 0;
  245.         Password[0]    = 0;
  246.         UserName[0]    = 0;
  247.         SendStartup    = FALSE;
  248.  
  249.         CurrentBBSName[0]    = 0;
  250.         CurrentBBSComment[0]    = 0;
  251.  
  252.         strcpy(CurrentBBSNumber,NumberBuffer);
  253.  
  254.         if(Config -> ModemConfig -> ConnectLimit > 0 && Config -> ModemConfig -> ConnectLimitMacro[0])
  255.         {
  256.             LimitCount = Config -> ModemConfig -> ConnectLimit;
  257.  
  258.             strcpy(LimitMacro,Config -> ModemConfig -> ConnectLimitMacro);
  259.         }
  260.         else
  261.             LimitCount = -1;
  262.  
  263.         LogAction(LocaleString(MSG_DIALPANEL_CONNECTED_TO_2_TXT),NumberBuffer);
  264.     }
  265.  
  266.         /* We are now online. */
  267.  
  268.     ObtainSemaphore(&OnlineSemaphore);
  269.  
  270.     Online = TRUE;
  271.  
  272.     ReleaseSemaphore(&OnlineSemaphore);
  273.  
  274.         /* Open auto-capture file. */
  275.  
  276.     if(Config -> CaptureConfig -> ConnectAutoCapture && Config -> CaptureConfig -> CapturePath[0])
  277.     {
  278.         if(DialNode -> Entry)
  279.             OpenAutoCaptureFile(DialNode -> Entry -> Header -> Name);
  280.         else
  281.             OpenAutoCaptureFile(LocaleString(MSG_DIALPANEL_CAPTURE_NAME_TXT));
  282.     }
  283.  
  284.         /* Remove node from
  285.          * dialing list and
  286.          * perform system
  287.          * setup.
  288.          */
  289.  
  290.     if(DialNode -> Entry)
  291.         RemoveDialNode(DialNode);
  292.  
  293.     Remove(&DialNode -> VanillaNode);
  294.  
  295.     FreeVecPooled(DialNode);
  296.  
  297.     if(PrivateConfig -> MiscConfig -> BackupConfig)
  298.     {
  299.         if(!BackupConfig)
  300.         {
  301.             if(BackupConfig = CreateConfiguration(TRUE))
  302.                 SaveConfig(PrivateConfig,BackupConfig);
  303.         }
  304.     }
  305.  
  306.         /* Make sure that the following
  307.          * setup/initialization will not
  308.          * touch the serial configuration.
  309.          */
  310.  
  311.     memcpy(PrivateConfig -> SerialConfig,Config -> SerialConfig,sizeof(struct SerialSettings));
  312.  
  313.     ConfigSetup();
  314.  
  315.         /* Reset the scanner. */
  316.  
  317.     FlowInit(TRUE);
  318. }
  319.  
  320.     /* OpenDialPanel(BOOL *Record):
  321.      *
  322.      *    Open the dialing panel.
  323.      */
  324.  
  325. STATIC LayoutHandle * __regargs
  326. OpenDialPanel(BOOL *Record)
  327. {
  328.     LayoutHandle *Handle;
  329.  
  330.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  331.         LH_LocaleHook,    &LocaleHook,
  332.     TAG_DONE))
  333.     {
  334.         LT_New(Handle,
  335.             LA_Type,    VERTICAL_KIND,
  336.         TAG_DONE);
  337.         {
  338.             LT_New(Handle,
  339.                 LA_Type,    VERTICAL_KIND,
  340.             TAG_DONE);
  341.             {
  342.                 LT_New(Handle,
  343.                     LA_Type,    VERTICAL_KIND,
  344.                 TAG_DONE);
  345.                 {
  346.                     LT_New(Handle,
  347.                         LA_Type,            BOX_KIND,
  348.                         LA_ID,                GAD_CALLING,
  349.                         LA_Chars,            45,
  350.                         LA_Lines,            4,
  351.                         LABX_ReserveSpace,    TRUE,
  352.                         LABX_FirstLabel,    MSG_DIALPANEL_CALLING_TXT,
  353.                         LABX_LastLabel,        MSG_DIALPANEL_NEXT_TXT,
  354.                     TAG_DONE);
  355.  
  356.                     LT_New(Handle,
  357.                         LA_Type,            BOX_KIND,
  358.                         LA_ID,                GAD_TIME,
  359.                         LA_Chars,            45,
  360.                         LA_Lines,            2,
  361.                         LABX_ReserveSpace,    TRUE,
  362.                         LABX_FirstLabel,    MSG_DIALPANEL_TIMEOUT_TXT,
  363.                         LABX_LastLabel,        MSG_DIALPANEL_ATTEMPT_TXT,
  364.                     TAG_DONE);
  365.  
  366.                     LT_New(Handle,
  367.                         LA_Type,            BOX_KIND,
  368.                         LA_ID,                GAD_NOTE,
  369.                         LA_Chars,            45,
  370.                         LA_Lines,            1,
  371.                         LABX_ReserveSpace,    TRUE,
  372.                         LABX_FirstLabel,    MSG_DIALPANEL_MESSAGE_TXT,
  373.                         LABX_LastLabel,        MSG_DIALPANEL_MESSAGE_TXT,
  374.                     TAG_DONE);
  375.  
  376.                     LT_EndGroup(Handle);
  377.                 }
  378.  
  379.                 LT_New(Handle,
  380.                     LA_Type,    VERTICAL_KIND,
  381.                 TAG_DONE);
  382.                 {
  383.                     LT_New(Handle,
  384.                         LA_Type,        XBAR_KIND,
  385.                     TAG_DONE);
  386.  
  387.                     LT_New(Handle,
  388.                         LA_Type,        CHECKBOX_KIND,
  389.                         LA_LabelID,        MSG_DIALPANEL_RECORD_ON_CONNECTION_TXT,
  390.                         LA_BOOL,        Record,
  391.                     TAG_DONE);
  392.  
  393.                     LT_EndGroup(Handle);
  394.                 }
  395.  
  396.                 LT_EndGroup(Handle);
  397.             }
  398.  
  399.             LT_New(Handle,
  400.                 LA_Type,VERTICAL_KIND,
  401.             TAG_DONE);
  402.             {
  403.                 LT_New(Handle,
  404.                     LA_Type,        XBAR_KIND,
  405.                     LAXB_FullSize,    TRUE,
  406.                 TAG_DONE);
  407.  
  408.                 LT_EndGroup(Handle);
  409.             }
  410.  
  411.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  412.                 LAGR_Spread,    TRUE,
  413.             TAG_DONE);
  414.             {
  415.                 LT_New(Handle,
  416.                     LA_Type,        BUTTON_KIND,
  417.                     LA_LabelID,        MSG_DIALPANEL_SKIP_GAD,
  418.                     LA_ID,            GAD_SKIP,
  419.                     LABT_ExtraFat,    TRUE,
  420.                     GA_Disabled,    TRUE,
  421.                 TAG_DONE);
  422.  
  423.                 LT_New(Handle,
  424.                     LA_Type,        BUTTON_KIND,
  425.                     LA_LabelID,        MSG_GLOBAL_REMOVE_GAD,
  426.                     LA_ID,            GAD_REMOVE,
  427.                     LABT_ExtraFat,    TRUE,
  428.                     GA_Disabled,    TRUE,
  429.                 TAG_DONE);
  430.  
  431.                 LT_New(Handle,
  432.                     LA_Type,        BUTTON_KIND,
  433.                     LA_LabelID,        MSG_DIALPANEL_GO_TO_ONLINE_GAD,
  434.                     LA_ID,            GAD_ONLINE,
  435.                     LABT_ReturnKey,    TRUE,
  436.                     LABT_ExtraFat,    TRUE,
  437.                 TAG_DONE);
  438.  
  439.                 LT_New(Handle,
  440.                     LA_Type,        BUTTON_KIND,
  441.                     LA_LabelID,        MSG_GLOBAL_ABORT_GAD,
  442.                     LA_ID,            GAD_ABORT,
  443.                     LABT_ExtraFat,    TRUE,
  444.                 TAG_DONE);
  445.  
  446.                 LT_EndGroup(Handle);
  447.             }
  448.  
  449.             LT_EndGroup(Handle);
  450.         }
  451.  
  452.         if(LT_Build(Handle,
  453.             LAWN_TitleID,        MSG_DIALPANEL_DIALING_TXT,
  454.             LAWN_IDCMP,            IDCMP_CLOSEWINDOW,
  455.             LAWN_HelpHook,        &GuideHook,
  456.             LAWN_Parent,        Window,
  457.             WA_DepthGadget,        TRUE,
  458.             WA_CloseGadget,        TRUE,
  459.             WA_DragBar,            TRUE,
  460.             WA_RMBTrap,            TRUE,
  461.             WA_Activate,        TRUE,
  462.         TAG_DONE))
  463.             return(Handle);
  464.         else
  465.             LT_DeleteHandle(Handle);
  466.     }
  467.  
  468.     return(NULL);
  469. }
  470.  
  471.     /* DialPanel():
  472.      *
  473.      *    This routine opens a small window in the middle of the
  474.      *    console window and walks down the list of numbers to
  475.      *    dial.
  476.      */
  477.  
  478. BOOL
  479. DialPanel()
  480. {
  481.     LayoutHandle    *Handle;
  482.     BOOL             Result = FALSE,
  483.                      Record = FALSE;
  484.  
  485.     BlockWindows();
  486.  
  487.     if(Handle = OpenDialPanel(&Record))
  488.     {
  489.         STATIC struct SerialSettings OriginalSerialConfig;
  490.  
  491.         struct Window        *PanelWindow = Handle -> Window;
  492.  
  493.         UBYTE                 ExitCommand[80],
  494.                              ExitBuffer[80],
  495.                               InitBuffer[80],
  496.                               PrefixBuffer[80],
  497.                               NumberBuffer[100];
  498.  
  499.         UBYTE                 DialBuffer[300];
  500.  
  501.         STRPTR                 NextExit,
  502.                              NextInit,
  503.                              NextPrefix,
  504.                              NextNumber;
  505.  
  506.         WORD                 NumberCount,
  507.                              NumberCurrent;
  508.  
  509.         LONG                 DialTimeout,
  510.                              DialRetries    = 0,
  511.                              DialAttempt    = 0;
  512.         struct PhoneNode    *DialNode        = NULL;
  513.  
  514.         LONG                 RedialTimeout;
  515.  
  516.         STRPTR                 CallingName;
  517.         UBYTE                 CallingBuffer[80];
  518.  
  519.         BOOL                 Dialing    = FALSE,
  520.                              Calling    = FALSE,
  521.                              Waiting    = FALSE,
  522.                              Skipping    = FALSE,
  523.                              Aborting    = FALSE,
  524.                              Error        = FALSE,
  525.                              Done        = FALSE,
  526.                              NeedHangUp    = TRUE;
  527.  
  528.         WORD                 RunCount    = 0;
  529.  
  530.         // Don't mix up the line send stuff with the default sending routine
  531.  
  532.         BYTE                (* LocalSendLine)(register STRPTR,register LONG);
  533.  
  534.         LocalSendLine    = SendLine;
  535.         SendLine        = SendLineDial;
  536.  
  537.             /* Reset the area code scanner data. */
  538.  
  539.         ObtainSemaphore(&PatternSemaphore);
  540.  
  541.         ChosenEntry        = NULL;
  542.         ChosenPattern    = NULL;
  543.  
  544.         ReleaseSemaphore(&PatternSemaphore);
  545.  
  546.             /* We are now dialing. */
  547.  
  548.         Status = STATUS_DIALING;
  549.  
  550.             /* Remember the original serial settings, so we
  551.              * can return to them later.
  552.              */
  553.  
  554.         CopyMem(Config -> SerialConfig,&OriginalSerialConfig,sizeof(struct SerialSettings));
  555.  
  556.             /* Set up the AmigaGuide help context. */
  557.  
  558.         GuideContext(CONTEXT_DIAL);
  559.  
  560.             /* No exit command is defined yet. */
  561.  
  562.         ExitCommand[0] = 0;
  563.  
  564.             /* Make the current one the active one. */
  565.  
  566.         LT_ShowWindow(Handle,TRUE);
  567.  
  568.         PushWindow(PanelWindow);
  569.  
  570.             /* Make a backup of the current configuration. */
  571.  
  572.         SaveConfig(Config,PrivateConfig);
  573.  
  574.             /* Don't echo serial output unless requested by the user. */
  575.  
  576.         if(!Config -> ModemConfig -> VerboseDialing)
  577.             Quiet = TRUE;
  578.  
  579.             /* Perform full sequence check. */
  580.  
  581.         FullCheck = TRUE;
  582.  
  583.             /* Reset the scanner. */
  584.  
  585.         FlowInit(TRUE);
  586.  
  587.             /* Clear the signals. */
  588.  
  589.         SetSignal(0,SIG_SKIP | SIG_BREAK);
  590.  
  591.             /* The big dialing loop. */
  592.  
  593.         do
  594.         {
  595.                 /* Any window input? */
  596.  
  597.             if(SetSignal(0,PORTMASK(PanelWindow -> UserPort)) & PORTMASK(PanelWindow -> UserPort))
  598.             {
  599.                 struct IntuiMessage    *Msg;
  600.                 ULONG                 MsgClass,
  601.                                      MsgQualifier;
  602.                 UWORD                 MsgCode;
  603.                 struct Gadget        *MsgGadget;
  604.  
  605.                 while(Msg = LT_GetIMsg(Handle))
  606.                 {
  607.                     MsgClass        = Msg -> Class;
  608.                     MsgCode            = Msg -> Code;
  609.                     MsgQualifier    = Msg -> Qualifier;
  610.                     MsgGadget        = Msg -> IAddress;
  611.  
  612.                     LT_ReplyIMsg(Msg);
  613.  
  614.                         /* Convert the space keypress into a
  615.                          * skip command.
  616.                          */
  617.  
  618.                     if(MsgClass == IDCMP_RAWKEY)
  619.                     {
  620.                         if((Dialing || Waiting) && LT_GetCode(MsgQualifier,MsgClass,MsgCode,MsgGadget) == ' ')
  621.                         {
  622.                             LT_PressButton(Handle,GAD_SKIP);
  623.  
  624.                             Skipping = TRUE;
  625.                         }
  626.                     }
  627.  
  628.                         /* Close the window, hang up the line,
  629.                          * return to the phone book.
  630.                          */
  631.  
  632.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  633.                         Aborting = Done = Result = TRUE;
  634.  
  635.                         /* So a button was pressed. */
  636.  
  637.                     if(MsgClass == IDCMP_GADGETUP)
  638.                     {
  639.                         switch(MsgGadget -> GadgetID)
  640.                         {
  641.                                 /* Remove the currently active dialing
  642.                                  * list entry.
  643.                                  */
  644.  
  645.                             case GAD_REMOVE:
  646.  
  647.                                     /* This makes sense only while
  648.                                      * we are dialing.
  649.                                      */
  650.  
  651.                                 if(Dialing)
  652.                                 {
  653.                                     struct PhoneNode    *NextNode = NULL;
  654.                                     BOOL                 UseHangUp;
  655.  
  656.                                         /* If still dialing, hang up first. */
  657.  
  658.                                     if(DialNode -> Entry && DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
  659.                                         UseHangUp = DialNode -> Entry -> Config -> ModemConfig -> AbortHangsUp;
  660.                                     else
  661.                                         UseHangUp = Config -> ModemConfig -> AbortHangsUp;
  662.  
  663.                                     if(UseHangUp)
  664.                                         HangUp();
  665.                                     else
  666.                                     {
  667.                                         SerWrite("\r",1);
  668.  
  669.                                         WaitTime(1,0);
  670.                                     }
  671.  
  672.                                         /* Ignore the response of the modem. */
  673.  
  674.                                     HandleSerial();
  675.  
  676.                                     FlowInit(TRUE);
  677.  
  678.                                         /* Is there another entry in the list? */
  679.  
  680.                                     if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
  681.                                         NextNode = (struct PhoneNode *)DialNode -> VanillaNode . ln_Succ;
  682.                                     else
  683.                                     {
  684.                                             /* No, there isn't; do we have a list with
  685.                                              * at least two entries in it?
  686.                                              */
  687.  
  688.                                         if(DialList -> lh_Head -> ln_Succ -> ln_Succ)
  689.                                         {
  690.                                                 /* Yet another dialing attempt coming up... */
  691.  
  692.                                             DialAttempt++;
  693.  
  694.                                                 /* Check for dial retry limit. */
  695.  
  696.                                             if(DialRetries >= 0 && DialAttempt >= DialRetries)
  697.                                             {
  698.                                                 PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  699.  
  700.                                                 WakeUp(PanelWindow,SOUND_BELL);
  701.  
  702.                                                 WaitTime(2,0);
  703.  
  704.                                                 Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  705.  
  706.                                                 Done = TRUE;
  707.                                             }
  708.                                             else
  709.                                             {
  710.                                                     /* Grab first list entry and continue. */
  711.  
  712.                                                 NextNode = (struct PhoneNode *)DialList -> lh_Head;
  713.                                             }
  714.                                         }
  715.                                         else
  716.                                         {
  717.                                                 /* That's all, folks! */
  718.  
  719.                                             PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIALING_LIST_IS_EMPTY_TXT));
  720.  
  721.                                             WaitTime(2,0);
  722.  
  723.                                             Done = TRUE;
  724.                                         }
  725.                                     }
  726.  
  727.                                         /* Remove dial entry from list. */
  728.  
  729.                                     if(DialNode -> Entry)
  730.                                         RemoveDialNode(DialNode);
  731.  
  732.                                     Remove(&DialNode -> VanillaNode);
  733.  
  734.                                     FreeVecPooled(DialNode);
  735.  
  736.                                         /* Is there an entry to proceed with? */
  737.  
  738.                                     if(DialNode = NextNode)
  739.                                     {
  740.                                         NextNumber = NULL;
  741.  
  742.                                         Calling = TRUE;
  743.                                     }
  744.                                 }
  745.  
  746.                                 break;
  747.  
  748.                             case GAD_SKIP:
  749.  
  750.                                 if(Dialing || Waiting)
  751.                                     Skipping = TRUE;
  752.  
  753.                                 break;
  754.  
  755.                             case GAD_ONLINE:
  756.  
  757.                                     /* Go online so soon? */
  758.  
  759.                                 if(!DialNode)
  760.                                 {
  761.                                     DialNode = (struct PhoneNode *)DialList -> lh_Head;
  762.  
  763.                                     if(DialNode -> Entry)
  764.                                         ExtractString(DialNode -> Entry -> Header -> Number,NumberBuffer,TRUE);
  765.                                     else
  766.                                         ExtractString(DialNode -> VanillaNode . ln_Name,NumberBuffer,TRUE);
  767.                                 }
  768.  
  769.                                 Connect(DialNode,NumberBuffer);
  770.  
  771.                                 Done = TRUE;
  772.  
  773.                                 break;
  774.  
  775.                                 /* Abort the dialing process. */
  776.  
  777.                             case GAD_ABORT:
  778.  
  779.                                 Aborting = Done = TRUE;
  780.  
  781.                                 break;
  782.                         }
  783.                     }
  784.  
  785.                     if(Done)
  786.                         break;
  787.                 }
  788.             }
  789.  
  790.                 /* Abort the process? */
  791.  
  792.             if(SetSignal(0,SIG_BREAK) & SIG_BREAK)
  793.             {
  794.                 if(!Done)
  795.                     Aborting = Done = TRUE;
  796.             }
  797.  
  798.                 /* Skip the current action? */
  799.  
  800.             if(SetSignal(0,SIG_SKIP) & SIG_SKIP)
  801.             {
  802.                 if((Dialing || Waiting) && !Done)
  803.                     Skipping = TRUE;
  804.             }
  805.  
  806.                 /* Are we to abort? */
  807.  
  808.             if(Aborting)
  809.             {
  810.                     /* Hang up if necessary. */
  811.  
  812.                 if(Dialing)
  813.                 {
  814.                     BOOL UseHangUp;
  815.  
  816.                     PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ABORTING_TXT));
  817.  
  818.                     if(DialNode -> Entry && DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
  819.                         UseHangUp = DialNode -> Entry -> Config -> ModemConfig -> AbortHangsUp;
  820.                     else
  821.                         UseHangUp = Config -> ModemConfig -> AbortHangsUp;
  822.  
  823.                     if(UseHangUp)
  824.                         HangUp();
  825.                     else
  826.                     {
  827.                         SerWrite("\r",1);
  828.                         WaitTime(1,0);
  829.                     }
  830.  
  831.                         /* Ignore the response of the modem. */
  832.  
  833.                     HandleSerial();
  834.  
  835.                     FlowInit(TRUE);
  836.                 }
  837.             }
  838.  
  839.                 /* Start at the beginning. */
  840.  
  841.             if(!DialNode && !Done)
  842.             {
  843.                 DialNode = (struct PhoneNode *)DialList -> lh_Head;
  844.  
  845.                 LT_SetAttributes(Handle,GAD_SKIP,
  846.                     GA_Disabled,    FALSE,
  847.                 TAG_DONE);
  848.  
  849.                 LT_SetAttributes(Handle,GAD_REMOVE,
  850.                     GA_Disabled,    FALSE,
  851.                 TAG_DONE);
  852.  
  853.                 Calling = TRUE;
  854.  
  855.                 NextNumber = NULL;
  856.             }
  857.  
  858.                 /* Are we to start a call? */
  859.  
  860.             if(Calling && !Done)
  861.             {
  862.                     /* Reset the sequence scanner, the user may have skipped
  863.                      * the previous dial attempt causing the modem to return
  864.                      * `NO CARRIER'. To prevent the dialer from skipping the
  865.                      * next dial entry as well as the previous we have to
  866.                      * flush any data pending on the serial line.
  867.                      */
  868.  
  869.                 FlowInit(TRUE);
  870.  
  871.                     /* Is this the first number for this dial entry? */
  872.  
  873.                 if(!NextNumber)
  874.                 {
  875.                     STRPTR    PhoneNumber;
  876.                     WORD    i,Len;
  877.  
  878.                         /* Does this entry have a configuration attached? */
  879.  
  880.                     if(DialNode -> Entry)
  881.                     {
  882.                             /* Get the phone number. */
  883.  
  884.                         PhoneNumber = DialNode -> Entry -> Header -> Number;
  885.  
  886.                             /* Pick up the modem configuration. */
  887.  
  888.                         if(DialNode -> Entry -> Config -> ModemConfig)
  889.                         {
  890.                             NextInit    = ExtractString(DialNode -> Entry -> Config -> ModemConfig -> ModemInit,    InitBuffer,        FALSE);
  891.                             NextExit    = ExtractString(DialNode -> Entry -> Config -> ModemConfig -> ModemExit,    ExitBuffer,        FALSE);
  892.                             NextPrefix    = ExtractString(DialNode -> Entry -> Config -> ModemConfig -> DialPrefix,    PrefixBuffer,    FALSE);
  893.                         }
  894.                         else
  895.                         {
  896.                             NextInit    = ExtractString(Config -> ModemConfig -> ModemInit,        InitBuffer,        FALSE);
  897.                             NextExit    = ExtractString(Config -> ModemConfig -> ModemExit,        ExitBuffer,        FALSE);
  898.                             NextPrefix    = ExtractString(Config -> ModemConfig -> DialPrefix,    PrefixBuffer,    FALSE);
  899.                         }
  900.                     }
  901.                     else
  902.                     {
  903.                             /* Get the phone number. */
  904.  
  905.                         PhoneNumber = DialNode -> VanillaNode . ln_Name;
  906.  
  907.                             /* Pick up the modem configuration. */
  908.  
  909.                         NextInit    = ExtractString(Config -> ModemConfig -> ModemInit,        InitBuffer,        FALSE);
  910.                         NextExit    = ExtractString(Config -> ModemConfig -> ModemExit,        ExitBuffer,        FALSE);
  911.                         NextPrefix    = ExtractString(Config -> ModemConfig -> DialPrefix,    PrefixBuffer,    FALSE);
  912.                     }
  913.  
  914.                             /* Extract the phone number. */
  915.  
  916.                     NextNumber = ExtractString(PhoneNumber,NumberBuffer,TRUE);
  917.  
  918.                         /* Count the number of phone numbers separated
  919.                          * by "|" characters.
  920.                          */
  921.  
  922.                     Len = strlen(PhoneNumber);
  923.  
  924.                     for(i = 0, NumberCount = 0 ; i < Len ; i++)
  925.                     {
  926.                         if(PhoneNumber[i] == '|')
  927.                         {
  928.                             WORD j;
  929.  
  930.                             for(j = i + 1 ; j <= Len ; j++)
  931.                             {
  932.                                 if(PhoneNumber[j] != ' ' && PhoneNumber[j] != 0)
  933.                                 {
  934.                                     if(PhoneNumber[j] != '|')
  935.                                         NumberCount++;
  936.  
  937.                                     break;
  938.                                 }
  939.                             }
  940.                         }
  941.                     }
  942.  
  943.                         /* This is the first one. */
  944.  
  945.                     NumberCurrent = 0;
  946.                 }
  947.                 else
  948.                 {
  949.                         /* Now for multiple phone numbers separated
  950.                          * by `|' characters. If `NextNumber' happens
  951.                          * to be zero, we will prepare to extract
  952.                          * the first phone number from the list.
  953.                          * In any other case we will try to obtain
  954.                          * the next number.
  955.                          */
  956.  
  957.                     NextNumber    = ExtractString(NextNumber,    NumberBuffer,    TRUE);
  958.                     NextInit    = ExtractString(NextInit,    InitBuffer,        FALSE);
  959.                     NextExit    = ExtractString(NextExit,    ExitBuffer,        FALSE);
  960.                     NextPrefix    = ExtractString(NextPrefix,    PrefixBuffer,    FALSE);
  961.  
  962.                     NumberCurrent++;
  963.                 }
  964.  
  965.                     /* Send the modem exit string before we
  966.                      * will need to reconfigure the serial
  967.                      * device driver.
  968.                      */
  969.  
  970.                 if(ExitCommand[0])
  971.                 {
  972.                     PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT));
  973.  
  974.                     FlowInit(TRUE);
  975.  
  976.                     SerialCommand(ExitCommand);
  977.  
  978.                     WaitTime(1,0);
  979.  
  980.                     HandleSerial();
  981.  
  982.                     if(FlowInfo . Changed && FlowInfo . Error)
  983.                     {
  984.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
  985.  
  986.                         WakeUp(PanelWindow,SOUND_ERROR);
  987.  
  988.                         Error = Done = TRUE;
  989.                     }
  990.                 }
  991.  
  992.                     /* We will need to change the serial parameters
  993.                      * in order to establish a connection.
  994.                      */
  995.  
  996.                 if(!Done)
  997.                 {
  998.                     if(DialNode -> Entry && DialNode -> Entry -> Config -> SerialConfig)
  999.                     {
  1000.                         if(ReconfigureSerial(PanelWindow,DialNode -> Entry -> Config -> SerialConfig) == RECONFIGURE_FAILURE)
  1001.                         {
  1002.                             WakeUp(PanelWindow,SOUND_ERROR);
  1003.  
  1004.                             Error = Done = TRUE;
  1005.                         }
  1006.                     }
  1007.                     else
  1008.                     {
  1009.                         if(ReconfigureSerial(PanelWindow,&OriginalSerialConfig) == RECONFIGURE_FAILURE)
  1010.                         {
  1011.                             WakeUp(PanelWindow,SOUND_ERROR);
  1012.  
  1013.                             Error = Done = TRUE;
  1014.                         }
  1015.                     }
  1016.                 }
  1017.  
  1018.                     /* Send the modem init command. */
  1019.  
  1020.                 if(InitBuffer[0] && !Done)
  1021.                 {
  1022.                     PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT));
  1023.  
  1024.                     FlowInit(TRUE);
  1025.  
  1026.                     SerialCommand(InitBuffer);
  1027.  
  1028.                     WaitTime(1,0);
  1029.  
  1030.                     HandleSerial();
  1031.  
  1032.                     if(FlowInfo . Changed && FlowInfo . Error)
  1033.                     {
  1034.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
  1035.  
  1036.                         WakeUp(PanelWindow,SOUND_ERROR);
  1037.  
  1038.                         Error = Done = TRUE;
  1039.                     }
  1040.                 }
  1041.  
  1042.                 if(!Done)
  1043.                 {
  1044.                         /* Remember the new exit command. */
  1045.  
  1046.                     strcpy(ExitCommand,ExitBuffer);
  1047.  
  1048.                     if(DialNode -> Entry)
  1049.                         CallingName = DialNode -> Entry -> Header -> Name;
  1050.                     else
  1051.                         CallingName = LocaleString(MSG_GLOBAL_UNKNOWN_TXT);
  1052.  
  1053.                         /* If there is more than one number to follow, say so. */
  1054.  
  1055.                     if(NumberCount)
  1056.                     {
  1057.                         UBYTE LocalBuffer[40];
  1058.  
  1059.                         SPrintf(LocalBuffer,LocaleString(MSG_DIALPANEL_ATTEMPT_OF_TXT),NumberCurrent + 1,NumberCount + 1);
  1060.  
  1061.                         SPrintf(CallingBuffer,"%s (%s)",CallingName,LocalBuffer);
  1062.  
  1063.                         CallingName = CallingBuffer;
  1064.                     }
  1065.  
  1066.                     PrintBox(Handle,GAD_CALLING,0,CallingName);
  1067.  
  1068.                         /* Show the comment if any. */
  1069.  
  1070.                     if(DialNode -> Entry && DialNode -> Entry -> Header -> Comment[0])
  1071.                         PrintBox(Handle,GAD_CALLING,1,DialNode -> Entry -> Header -> Comment);
  1072.                     else
  1073.                         PrintBox(Handle,GAD_CALLING,1,"-");
  1074.  
  1075.                         /* Display the number being called. */
  1076.  
  1077.                     if(DialNode -> Entry)
  1078.                         Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),DialNode -> Entry -> Header -> Name);
  1079.                     else
  1080.                         Say(LocaleString(MSG_DIALPANEL_NOW_CALLING_TXT),NumberBuffer);
  1081.  
  1082.                     PrintBox(Handle,GAD_CALLING,2,NumberBuffer);
  1083.  
  1084.                         /* Display the name of the service to call next. */
  1085.  
  1086.                     if(NextNumber)
  1087.                     {
  1088.                         if(DialNode -> Entry)
  1089.                             CallingName = DialNode -> Entry -> Header -> Name;
  1090.                         else
  1091.                             CallingName = DialNode -> VanillaNode . ln_Name;
  1092.                     }
  1093.                     else
  1094.                     {
  1095.                         if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
  1096.                         {
  1097.                             if(DialNode -> Entry)
  1098.                                 CallingName = ((struct PhoneNode *)DialNode -> VanillaNode . ln_Succ) -> Entry -> Header -> Name;
  1099.                             else
  1100.                                 CallingName = DialNode -> VanillaNode . ln_Succ -> ln_Name;
  1101.                         }
  1102.                         else
  1103.                             CallingName = "-";
  1104.                     }
  1105.  
  1106.                     PrintBox(Handle,GAD_CALLING,3,CallingName);
  1107.  
  1108.                         /* Right now we're dialing. */
  1109.  
  1110.                     PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIALING_TXT));
  1111.  
  1112.                         /* Build the dialing command. */
  1113.  
  1114.                     strcpy(DialBuffer,PrefixBuffer);
  1115.                     strcat(DialBuffer,NumberBuffer);
  1116.  
  1117.                     if(DialNode -> Entry)
  1118.                     {
  1119.                         if(DialNode -> Entry -> Config -> ModemConfig)
  1120.                             strcat(DialBuffer,DialNode -> Entry -> Config -> ModemConfig -> DialSuffix);
  1121.                         else
  1122.                             strcat(DialBuffer,Config -> ModemConfig -> DialSuffix);
  1123.                     }
  1124.                     else
  1125.                         strcat(DialBuffer,Config -> ModemConfig -> DialSuffix);
  1126.  
  1127.                         /* Pick up dial timeout and dial retries. */
  1128.  
  1129.                     if(DialNode -> Entry && DialNode -> Entry -> Config -> ModemConfig)
  1130.                     {
  1131.                         DialTimeout    = DialNode -> Entry -> Config -> ModemConfig -> DialTimeout;
  1132.                         DialRetries    = DialNode -> Entry -> Config -> ModemConfig -> DialRetries;
  1133.                     }
  1134.                     else
  1135.                     {
  1136.                         DialTimeout    = Config -> ModemConfig -> DialTimeout;
  1137.                         DialRetries    = Config -> ModemConfig -> DialRetries;
  1138.                     }
  1139.  
  1140.                         /* Dial the number. */
  1141.  
  1142.                     SerialCommand(DialBuffer);
  1143.  
  1144.                         /* Now we should be dialing. */
  1145.  
  1146.                     Calling = FALSE;
  1147.                     Dialing = TRUE;
  1148.  
  1149.                         /* For the sake of precision. */
  1150.  
  1151.                     RunCount = 0;
  1152.                 }
  1153.             }
  1154.  
  1155.                 /* Are we to skip the current assignment? */
  1156.  
  1157.             if(Skipping && !Done)
  1158.             {
  1159.                 Skipping = FALSE;
  1160.  
  1161.                     /* Are we currently dialing? */
  1162.  
  1163.                 if(Dialing)
  1164.                 {
  1165.                         /* Hang up if necessary. */
  1166.  
  1167.                     if(NeedHangUp)
  1168.                     {
  1169.                         BOOL UseHangUp;
  1170.  
  1171.                         if(DialNode -> Entry && DialNode -> Entry -> Config && DialNode -> Entry -> Config -> ModemConfig)
  1172.                             UseHangUp = DialNode -> Entry -> Config -> ModemConfig -> AbortHangsUp;
  1173.                         else
  1174.                             UseHangUp = Config -> ModemConfig -> AbortHangsUp;
  1175.  
  1176.                         if(UseHangUp)
  1177.                             HangUp();
  1178.                         else
  1179.                         {
  1180.                             SerWrite("\r",1);
  1181.                             WaitTime(1,0);
  1182.                         }
  1183.                     }
  1184.                     else
  1185.                         NeedHangUp = TRUE;
  1186.  
  1187.                         /* Ignore the response of the modem. */
  1188.  
  1189.                     HandleSerial();
  1190.  
  1191.                     FlowInit(TRUE);
  1192.  
  1193.                         /* Did we dial all the numbers available? */
  1194.  
  1195.                     if(!NextNumber)
  1196.                     {
  1197.                             /* Is this one the last entry? */
  1198.  
  1199.                         if(DialNode -> VanillaNode . ln_Succ -> ln_Succ)
  1200.                         {
  1201.                             LONG InterDialDelay;
  1202.  
  1203.                                 /* There is still another entry. */
  1204.  
  1205.                             DialNode = (struct PhoneNode *)DialNode -> VanillaNode . ln_Succ;
  1206.  
  1207.                                 /* Get the inter-dial delay. */
  1208.  
  1209.                             if(DialNode -> Entry)
  1210.                             {
  1211.                                 if(DialNode -> Entry -> Config -> ModemConfig)
  1212.                                     InterDialDelay = DialNode -> Entry -> Config -> ModemConfig -> InterDialDelay;
  1213.                                 else
  1214.                                     InterDialDelay = Config -> ModemConfig -> InterDialDelay;
  1215.                             }
  1216.                             else
  1217.                                 InterDialDelay = Config -> ModemConfig -> InterDialDelay;
  1218.  
  1219.                                 /* Check if we should wait before we fire off another dial command. */
  1220.  
  1221.                             if(InterDialDelay)
  1222.                             {
  1223.                                     /* Wait until the inter-dial delay has elapsed. */
  1224.  
  1225.                                 RedialTimeout = InterDialDelay;
  1226.  
  1227.                                 PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_WAITING_TO_CALL_TXT));
  1228.  
  1229.                                 Dialing = FALSE;
  1230.                                 Waiting = TRUE;
  1231.  
  1232.                                     /* For the sake of precision. */
  1233.  
  1234.                                 RunCount = 0;
  1235.  
  1236.                                 Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));
  1237.  
  1238.                                     /* No entry is currently being called. */
  1239.  
  1240.                                 PrintBox(Handle,GAD_CALLING,0,"-");
  1241.                                 PrintBox(Handle,GAD_CALLING,1,"-");
  1242.                                 PrintBox(Handle,GAD_CALLING,2,"-");
  1243.  
  1244.                                 LT_SetAttributes(Handle,GAD_REMOVE,
  1245.                                     GA_Disabled,    TRUE,
  1246.                                 TAG_DONE);
  1247.  
  1248.                                     /* Display name of entry to call next. */
  1249.  
  1250.                                 if(DialNode -> Entry)
  1251.                                     PrintBox(Handle,GAD_CALLING,3,DialNode -> Entry -> Header -> Name);
  1252.                                 else
  1253.                                     PrintBox(Handle,GAD_CALLING,3,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));
  1254.                             }
  1255.                             else
  1256.                             {
  1257.                                 Dialing = FALSE;
  1258.                                 Calling = TRUE;
  1259.                             }
  1260.                         }
  1261.                         else
  1262.                         {
  1263.                                 /* Yet another dial attempt coming up. */
  1264.  
  1265.                             DialAttempt++;
  1266.  
  1267.                                 /* Is this one the last dial
  1268.                                  * attempt to be made?
  1269.                                  */
  1270.  
  1271.                             if(DialAttempt >= DialRetries && DialRetries >= 0)
  1272.                             {
  1273.                                 PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  1274.  
  1275.                                 WakeUp(PanelWindow,SOUND_BELL);
  1276.  
  1277.                                 WaitTime(2,0);
  1278.  
  1279.                                 Say(LocaleString(MSG_DIALPANEL_MAXIMUM_NUMBER_OF_DIAL_RETRIES_TXT));
  1280.  
  1281.                                 Done = TRUE;
  1282.                             }
  1283.                             else
  1284.                             {
  1285.                                 LONG InterDialDelay;
  1286.  
  1287.                                     /* Get the first list entry. */
  1288.  
  1289.                                 DialNode = (struct PhoneNode *)DialList -> lh_Head;
  1290.  
  1291.                                 NextNumber = NULL;
  1292.  
  1293.                                     /* Get the redial delay. */
  1294.  
  1295.                                 if(DialNode -> Entry)
  1296.                                 {
  1297.                                     if(DialNode -> Entry -> Config -> ModemConfig)
  1298.                                     {
  1299.                                         RedialTimeout    = DialNode -> Entry -> Config -> ModemConfig -> RedialDelay;
  1300.                                         InterDialDelay    = DialNode -> Entry -> Config -> ModemConfig -> InterDialDelay;
  1301.                                     }
  1302.                                     else
  1303.                                     {
  1304.                                         RedialTimeout    = Config -> ModemConfig -> RedialDelay;
  1305.                                         InterDialDelay    = Config -> ModemConfig -> InterDialDelay;
  1306.                                     }
  1307.                                 }
  1308.                                 else
  1309.                                 {
  1310.                                     RedialTimeout    = Config -> ModemConfig -> RedialDelay;
  1311.                                     InterDialDelay    = Config -> ModemConfig -> InterDialDelay;
  1312.                                 }
  1313.  
  1314.                                     /* Check if the inter-dial delay is larger than
  1315.                                      * the redial delay. If so, use the inter-dial delay.
  1316.                                      */
  1317.  
  1318.                                 if(InterDialDelay > RedialTimeout)
  1319.                                     RedialTimeout = InterDialDelay;
  1320.  
  1321.                                     /* No redial delay? Restart dialing... */
  1322.  
  1323.                                 if(!RedialTimeout)
  1324.                                 {
  1325.                                     Dialing = FALSE;
  1326.                                     Calling = TRUE;
  1327.  
  1328.                                     WaitTime(1,0);
  1329.                                 }
  1330.                                 else
  1331.                                 {
  1332.                                         /* Go into redial delay. */
  1333.  
  1334.                                     PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_REDIAL_DELAY_TXT));
  1335.  
  1336.                                     Dialing = FALSE;
  1337.                                     Waiting = TRUE;
  1338.  
  1339.                                         /* For the sake of precision. */
  1340.  
  1341.                                     RunCount = 0;
  1342.  
  1343.                                     Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));
  1344.  
  1345.                                         /* No entry is currently being called. */
  1346.  
  1347.                                     PrintBox(Handle,GAD_CALLING,0,"-");
  1348.                                     PrintBox(Handle,GAD_CALLING,1,"-");
  1349.                                     PrintBox(Handle,GAD_CALLING,2,"-");
  1350.  
  1351.                                     LT_SetAttributes(Handle,GAD_REMOVE,
  1352.                                         GA_Disabled,    TRUE,
  1353.                                     TAG_DONE);
  1354.  
  1355.                                         /* Display name of entry to call next. */
  1356.  
  1357.                                     if(DialNode -> Entry)
  1358.                                         PrintBox(Handle,GAD_CALLING,3,DialNode -> Entry -> Header -> Name);
  1359.                                     else
  1360.                                         PrintBox(Handle,GAD_CALLING,3,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));
  1361.                                 }
  1362.                             }
  1363.                         }
  1364.                     }
  1365.                     else
  1366.                     {
  1367.                         LONG InterDialDelay;
  1368.  
  1369.                             /* Get the inter-dial delay. */
  1370.  
  1371.                         if(DialNode -> Entry)
  1372.                         {
  1373.                             if(DialNode -> Entry -> Config -> ModemConfig)
  1374.                                 InterDialDelay = DialNode -> Entry -> Config -> ModemConfig -> InterDialDelay;
  1375.                             else
  1376.                                 InterDialDelay = Config -> ModemConfig -> InterDialDelay;
  1377.                         }
  1378.                         else
  1379.                             InterDialDelay = Config -> ModemConfig -> InterDialDelay;
  1380.  
  1381.                             /* Check if we should wait before we fire off another dial command. */
  1382.  
  1383.                         if(InterDialDelay)
  1384.                         {
  1385.                                 /* Wait until the inter-dial delay has elapsed. */
  1386.  
  1387.                             RedialTimeout = InterDialDelay;
  1388.  
  1389.                             PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_WAITING_TO_CALL_TXT));
  1390.  
  1391.                             Dialing = FALSE;
  1392.                             Waiting = TRUE;
  1393.  
  1394.                                 /* For the sake of precision. */
  1395.  
  1396.                             RunCount = 0;
  1397.  
  1398.                             Say(LocaleString(MSG_DIALPANEL_WAITING_TXT));
  1399.  
  1400.                                 /* No entry is currently being called. */
  1401.  
  1402.                             PrintBox(Handle,GAD_CALLING,0,"-");
  1403.                             PrintBox(Handle,GAD_CALLING,1,"-");
  1404.                             PrintBox(Handle,GAD_CALLING,2,"-");
  1405.  
  1406.                             LT_SetAttributes(Handle,GAD_REMOVE,
  1407.                                 GA_Disabled,    TRUE,
  1408.                             TAG_DONE);
  1409.  
  1410.                                 /* Display name of entry to call next. */
  1411.  
  1412.                             if(DialNode -> Entry)
  1413.                                 PrintBox(Handle,GAD_CALLING,3,DialNode -> Entry -> Header -> Name);
  1414.                             else
  1415.                                 PrintBox(Handle,GAD_CALLING,3,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));
  1416.                         }
  1417.                         else
  1418.                         {
  1419.                             Dialing = FALSE;
  1420.                             Calling = TRUE;
  1421.                         }
  1422.                     }
  1423.                 }
  1424.                 else
  1425.                 {
  1426.                         /* Stop waiting. */
  1427.  
  1428.                     if(Waiting)
  1429.                     {
  1430.                         LT_SetAttributes(Handle,GAD_REMOVE,
  1431.                             GA_Disabled,    FALSE,
  1432.                         TAG_DONE);
  1433.  
  1434.                         Waiting = FALSE;
  1435.                         Calling = TRUE;
  1436.                     }
  1437.                 }
  1438.             }
  1439.  
  1440.                 /* Take care of serial input. */
  1441.  
  1442.             if(!Done)
  1443.                 HandleSerial();
  1444.  
  1445.                 /* Any news from the modem? */
  1446.  
  1447.             if(!Done && FlowInfo . Changed)
  1448.             {
  1449.                     /* Current number is busy. */
  1450.  
  1451.                 if(FlowInfo . Busy || (FlowInfo . NoCarrier && Config -> ModemConfig -> NoCarrierIsBusy))
  1452.                 {
  1453.                     FlowInit(TRUE);
  1454.  
  1455.                     if(Dialing && !Done)
  1456.                     {
  1457.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));
  1458.  
  1459.                         Say(LocaleString(MSG_DIALPANEL_LINE_IS_BUSY_TXT));
  1460.  
  1461.                         WaitTime(1,0);
  1462.  
  1463.                         Skipping = TRUE;
  1464.  
  1465.                         NeedHangUp = FALSE;
  1466.                     }
  1467.                 }
  1468.  
  1469.                     /* Line does not feature a dialtone. */
  1470.  
  1471.                 if(FlowInfo . NoDialTone)
  1472.                 {
  1473.                     FlowInit(TRUE);
  1474.  
  1475.                     if(Dialing && !Done)
  1476.                     {
  1477.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));
  1478.  
  1479.                         WakeUp(PanelWindow,SOUND_ERROR);
  1480.  
  1481.                         Say(LocaleString(MSG_DIALPANEL_NO_DIALTONE_TXT));
  1482.  
  1483.                         Error = Done = TRUE;
  1484.                     }
  1485.                 }
  1486.  
  1487.                     /* Somebody tries to call us. */
  1488.  
  1489.                 if(FlowInfo . Ring)
  1490.                 {
  1491.                     FlowInit(TRUE);
  1492.  
  1493.                     if(!Done)
  1494.                     {
  1495.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));
  1496.  
  1497.                         WakeUp(PanelWindow,SOUND_RING);
  1498.  
  1499.                         Say(LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT));
  1500.  
  1501.                         Error = Done = TRUE;
  1502.                     }
  1503.                 }
  1504.  
  1505.                     /* Somebody's talking. */
  1506.  
  1507.                 if(FlowInfo . Voice)
  1508.                 {
  1509.                     FlowInit(TRUE);
  1510.  
  1511.                     if(!Done)
  1512.                     {
  1513.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));
  1514.  
  1515.                         WakeUp(PanelWindow,SOUND_VOICE);
  1516.  
  1517.                         Say(LocaleString(MSG_DIALPANEL_INCOMING_VOICE_CALL_TXT));
  1518.  
  1519.                         Error = Done = TRUE;
  1520.                     }
  1521.                 }
  1522.  
  1523.                     /* We got a connect. */
  1524.  
  1525.                 if(FlowInfo . Connect)
  1526.                 {
  1527.                     FlowInit(TRUE);
  1528.  
  1529.                     if(Dialing && !Done)
  1530.                     {
  1531.                             /* Make the connection. */
  1532.  
  1533.                         Connect(DialNode,NumberBuffer);
  1534.  
  1535.                         Done = TRUE;
  1536.  
  1537.                             /* Wake the user up. */
  1538.  
  1539.                         if(BaudBuffer[0])
  1540.                         {
  1541.                             PrintBox(Handle,GAD_NOTE,0,"CONNECT %s",BaudBuffer);
  1542.  
  1543.                             WakeUp(PanelWindow,SOUND_CONNECT);
  1544.  
  1545.                             WaitTime(2,0);
  1546.  
  1547.                                 /* Install new baud rate if desired. */
  1548.  
  1549.                             if(Config -> ModemConfig -> ConnectAutoBaud && DTERate > 110)
  1550.                             {
  1551.                                 Config -> SerialConfig -> BaudRate = DTERate;
  1552.  
  1553.                                 ReconfigureSerial(PanelWindow,NULL);
  1554.                             }
  1555.                         }
  1556.                         else
  1557.                         {
  1558.                             PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));
  1559.  
  1560.                             WakeUp(PanelWindow,SOUND_CONNECT);
  1561.                         }
  1562.  
  1563.                         Say(LocaleString(MSG_DIALPANEL_CONNECTION_ESTABLISHED_TXT));
  1564.                     }
  1565.                 }
  1566.  
  1567.                     /* Looks like an error. */
  1568.  
  1569.                 if(FlowInfo . Error)
  1570.                 {
  1571.                     FlowInit(TRUE);
  1572.  
  1573.                     if(Dialing && !Done)
  1574.                     {
  1575.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
  1576.  
  1577.                         WakeUp(PanelWindow,SOUND_ERROR);
  1578.  
  1579.                         Error = Done = TRUE;
  1580.                     }
  1581.                 }
  1582.  
  1583.                     /* In any other case, reset the scanner. */
  1584.  
  1585.                 FlowInit(TRUE);
  1586.             }
  1587.  
  1588.                 /* If nothing special's up... */
  1589.  
  1590.             if(!Done && !Skipping && (Dialing || Waiting))
  1591.             {
  1592.                     /* Wait half a second. */
  1593.  
  1594.                 WaitTime(0,MILLION / 2);
  1595.  
  1596.                 if(Dialing)
  1597.                 {
  1598.                     PrintBox(Handle,GAD_TIME,0,"%2ld:%02ld",DialTimeout / 60,DialTimeout % 60);
  1599.  
  1600.                     if(DialRetries < 0)
  1601.                         PrintBox(Handle,GAD_TIME,1,LocaleString(MSG_DIAL_RETRIES_UNLIMITED_TXT));
  1602.                     else
  1603.                         PrintBox(Handle,GAD_TIME,1,LocaleString(MSG_DIALPANEL_ATTEMPT_OF_TXT),DialAttempt + 1,DialRetries);
  1604.                 }
  1605.  
  1606.                 if(Waiting)
  1607.                     PrintBox(Handle,GAD_TIME,0,"%2ld:%02ld",RedialTimeout / 60,RedialTimeout % 60);
  1608.  
  1609.                     /* The following instructions are executed each second */
  1610.  
  1611.                 if(RunCount++)
  1612.                 {
  1613.                     RunCount = 0;
  1614.  
  1615.                         /* Are we dialing? */
  1616.  
  1617.                     if(Dialing)
  1618.                     {
  1619.                             /* Yet another second has elapsed. */
  1620.  
  1621.                         if(DialTimeout > 0)
  1622.                             DialTimeout--;
  1623.  
  1624.                             /* Has the dial timeout elapsed without
  1625.                              * a connection being made?
  1626.                              */
  1627.  
  1628.                         if(!DialTimeout)
  1629.                         {
  1630.                             PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_DIAL_ATTEMPT_TIMEOUT_TXT));
  1631.  
  1632.                             Skipping = TRUE;
  1633.                         }
  1634.                     }
  1635.  
  1636.                         /* Are we waiting? */
  1637.  
  1638.                     if(Waiting)
  1639.                     {
  1640.                             /* Yet another second has elapsed. */
  1641.  
  1642.                         if(RedialTimeout > 0)
  1643.                             RedialTimeout--;
  1644.  
  1645.                             /* The redial delay has elapsed,
  1646.                              * start dialing again.
  1647.                              */
  1648.  
  1649.                         if(!RedialTimeout)
  1650.                             Skipping = TRUE;
  1651.                     }
  1652.                 }
  1653.             }
  1654.         }
  1655.         while(!Done);
  1656.  
  1657.             /* Are we online or not? */
  1658.  
  1659.         ObtainSemaphore(&OnlineSemaphore);
  1660.  
  1661.         if(!Online)
  1662.         {
  1663.             ReleaseSemaphore(&OnlineSemaphore);
  1664.  
  1665.                 /* Is the serial setup different? */
  1666.  
  1667.             if(memcmp(Config -> SerialConfig,&OriginalSerialConfig,sizeof(struct SerialSettings)))
  1668.             {
  1669.                     /* Set up the old serial configuration. */
  1670.  
  1671.                 if(ReconfigureSerial(PanelWindow,&OriginalSerialConfig) != RECONFIGURE_FAILURE)
  1672.                 {
  1673.                         /* Send the exit command if necessary. */
  1674.  
  1675.                     if(ExitCommand[0])
  1676.                     {
  1677.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_SENDING_MODEM_EXIT_COMMAND_TXT));
  1678.  
  1679.                         FlowInit(TRUE);
  1680.  
  1681.                         SerialCommand(ExitCommand);
  1682.  
  1683.                         WaitTime(1,0);
  1684.  
  1685.                         HandleSerial();
  1686.  
  1687.                         if(FlowInfo . Changed && FlowInfo . Error)
  1688.                         {
  1689.                             PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
  1690.  
  1691.                             WakeUp(PanelWindow,SOUND_ERROR);
  1692.  
  1693.                             Error = TRUE;
  1694.                         }
  1695.                     }
  1696.  
  1697.                         /* Take care of the init command if necessary. */
  1698.  
  1699.                     if(Config -> ModemConfig -> ModemInit[0] && !Error)
  1700.                     {
  1701.                         PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_SENDING_MODEM_INIT_COMMAND_TXT));
  1702.  
  1703.                         FlowInit(TRUE);
  1704.  
  1705.                         SerialCommand(Config -> ModemConfig -> ModemInit);
  1706.  
  1707.                         WaitTime(1,0);
  1708.  
  1709.                         HandleSerial();
  1710.  
  1711.                         if(FlowInfo . Changed && FlowInfo . Error)
  1712.                         {
  1713.                             PrintBox(Handle,GAD_NOTE,0,LocaleString(MSG_DIALPANEL_ERROR_SENDING_MODEM_COMMAND_TXT));
  1714.  
  1715.                             WakeUp(PanelWindow,SOUND_ERROR);
  1716.  
  1717.                             Error = TRUE;
  1718.                         }
  1719.                     }
  1720.                 }
  1721.             }
  1722.         }
  1723.         else
  1724.             ReleaseSemaphore(&OnlineSemaphore);
  1725.  
  1726.             /* Make sure the error gets displayed. */
  1727.  
  1728.         if(Error)
  1729.         {
  1730.             struct IntuiMessage    *Msg;
  1731.             ULONG                 MsgClass;
  1732.             WORD                 i;
  1733.  
  1734.             for(i = GAD_SKIP ; i <= GAD_REMOVE ; i++)
  1735.                 LT_SetAttributes(Handle,i,GA_Disabled,TRUE,TAG_DONE);
  1736.  
  1737.             Done = FALSE;
  1738.  
  1739.             do
  1740.             {
  1741.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1742.                     break;
  1743.  
  1744.                 while(Msg = LT_GetIMsg(Handle))
  1745.                 {
  1746.                     MsgClass = Msg -> Class;
  1747.  
  1748.                     LT_ReplyIMsg(Msg);
  1749.  
  1750.                     if(MsgClass == IDCMP_CLOSEWINDOW || MsgClass == IDCMP_GADGETUP)
  1751.                         Done = TRUE;
  1752.                 }
  1753.             }
  1754.             while(!Done);
  1755.         }
  1756.  
  1757.             // Put back the old routine if necessary
  1758.  
  1759.         if(SendLine == SendLineDial)
  1760.             SendLine = LocalSendLine;
  1761.  
  1762.         PopWindow();
  1763.  
  1764.         LT_DeleteHandle(Handle);
  1765.  
  1766.             /* Reset the scanner. */
  1767.  
  1768.         FullCheck = FALSE;
  1769.  
  1770.         FlowInit(TRUE);
  1771.  
  1772.             /* We are done now, restart echoing serial */
  1773.  
  1774.         Quiet = FALSE;
  1775.  
  1776.         ReleaseWindows();
  1777.  
  1778.             /* Reset the display if necessary. */
  1779.  
  1780.         if(ResetDisplay)
  1781.         {
  1782.             if(!DisplayReset())
  1783.                 return(FALSE);
  1784.         }
  1785.  
  1786.             /* Handle online jobs. */
  1787.  
  1788.         ObtainSemaphore(&OnlineSemaphore);
  1789.  
  1790.         if(Online)
  1791.         {
  1792.             ReleaseSemaphore(&OnlineSemaphore);
  1793.  
  1794.             SetDialMenu(FALSE);
  1795.  
  1796.                 /* Send the startup macro if necessary. */
  1797.  
  1798.             if(SendStartup)
  1799.             {
  1800.                 if(Config -> CommandConfig -> LoginMacro[0])
  1801.                     SerialCommand(Config -> CommandConfig -> LoginMacro);
  1802.  
  1803.                 if(Config -> CommandConfig -> StartupMacro[0])
  1804.                     SerialCommand(Config -> CommandConfig -> StartupMacro);
  1805.  
  1806.                 SendStartup = FALSE;
  1807.             }
  1808.  
  1809.                 /* Take care of the recording feature. */
  1810.  
  1811.             if(Record)
  1812.             {
  1813.                 if(CreateRecord(CurrentBBSName[0] ? CurrentBBSName : CurrentBBSNumber))
  1814.                 {
  1815.                     RememberResetOutput();
  1816.                     RememberResetInput();
  1817.  
  1818.                     RememberOutput = TRUE;
  1819.  
  1820.                     Recording = TRUE;
  1821.                     RecordingLine = FALSE;
  1822.  
  1823.                     OnItem(MEN_RECORD_LINE);
  1824.  
  1825.                     CheckItem(MEN_RECORD,TRUE);
  1826.                     CheckItem(MEN_RECORD_LINE,FALSE);
  1827.                 }
  1828.             }
  1829.         }
  1830.         else
  1831.         {
  1832.             ReleaseSemaphore(&OnlineSemaphore);
  1833.  
  1834.             SetDialMenu(TRUE);
  1835.         }
  1836.     }
  1837.     else
  1838.         ReleaseWindows();
  1839.  
  1840.         /* Reply to the message that started the
  1841.          * dialing process.
  1842.          */
  1843.  
  1844.     ObtainSemaphore(&OnlineSemaphore);
  1845.  
  1846.     Forbid();
  1847.  
  1848.     if(DialMsg)
  1849.     {
  1850.         if(Online)
  1851.             DialMsg -> rm_Result1 = RC_OK;
  1852.         else
  1853.             DialMsg -> rm_Result1 = RC_WARN;
  1854.  
  1855.         DialMsg -> rm_Result2 = 0;
  1856.  
  1857.         ReplyMsg(DialMsg);
  1858.  
  1859.         DialMsg = NULL;
  1860.     }
  1861.  
  1862.     Permit();
  1863.  
  1864.     ReleaseSemaphore(&OnlineSemaphore);
  1865.  
  1866.     return(Result);
  1867. }
  1868.